<template>
  <view class="pull-refresh" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
    <view class="refresh-indicator" :style="{ height: `${indicatorHeight}px`, opacity: indicatorOpacity }">
      <view class="refresh-content" :class="{ 'refreshing': isRefreshing }">
        <uni-icons v-if="!isRefreshing" type="arrowdown" size="20" color="#999" :style="{ transform: `rotate(${arrowRotate}deg)` }"></uni-icons>
        <uni-load-more v-else status="loading" :content-text="{ contentdown: '', contentrefresh: '正在刷新...', contentnomore: '' }"></uni-load-more>
        <text class="refresh-text">{{ refreshText }}</text>
      </view>
    </view>
    <view class="refresh-content-wrapper" :style="{ transform: `translateY(${translateY}px)` }">
      <slot></slot>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';

interface Props {
  threshold?: number; // 触发刷新的阈值
  maxDistance?: number; // 最大下拉距离
}

interface Emits {
  (e: 'refresh'): void;
}

const props = withDefaults(defineProps<Props>(), {
  threshold: 60,
  maxDistance: 120,
});

const emit = defineEmits<Emits>();

const translateY = ref(0);
const startY = ref(0);
const isDragging = ref(false);
const isRefreshing = ref(false);
const canRefresh = ref(false);

const indicatorHeight = computed(() => Math.min(translateY.value, props.maxDistance));
const indicatorOpacity = computed(() => Math.min(translateY.value / props.threshold, 1));
const arrowRotate = computed(() => canRefresh.value ? 180 : 0);

const refreshText = computed(() => {
  if (isRefreshing.value) return '正在刷新...';
  if (canRefresh.value) return '释放刷新';
  return '下拉刷新';
});

const handleTouchStart = (e: TouchEvent) => {
  if (isRefreshing.value) return;
  
  startY.value = e.touches[0].clientY;
  isDragging.value = true;
};

const handleTouchMove = (e: TouchEvent) => {
  if (!isDragging.value || isRefreshing.value) return;
  
  const currentY = e.touches[0].clientY;
  const deltaY = currentY - startY.value;
  
  // 只允许向下拉动
  if (deltaY > 0) {
    // 添加阻尼效果
    const damping = 0.5;
    translateY.value = Math.min(deltaY * damping, props.maxDistance);
    
    // 判断是否可以刷新
    canRefresh.value = translateY.value >= props.threshold;
  }
};

const handleTouchEnd = () => {
  if (!isDragging.value || isRefreshing.value) return;
  
  isDragging.value = false;
  
  if (canRefresh.value) {
    // 触发刷新
    isRefreshing.value = true;
    translateY.value = props.threshold;
    emit('refresh');
  } else {
    // 回弹
    translateY.value = 0;
    canRefresh.value = false;
  }
};

// 完成刷新
const finishRefresh = () => {
  isRefreshing.value = false;
  canRefresh.value = false;
  translateY.value = 0;
};

defineExpose({
  finishRefresh,
});
</script>

<style lang="scss" scoped>
.pull-refresh {
  position: relative;
  overflow: hidden;
}

.refresh-indicator {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  background-color: #f8f9fa;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  padding-bottom: 10px;
  transform: translateY(-100%);
}

.refresh-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition: transform 0.3s ease;
  
  &.refreshing {
    .uni-icons {
      animation: rotate 1s linear infinite;
    }
  }
}

.refresh-text {
  font-size: 14px;
  color: #666;
}

.refresh-content-wrapper {
  transition: transform 0.3s ease;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>